package com.cskaoyan.javase.oop3._2inner._3local._4life;

/**
 * 在局部内部类的成员方法中，如果想要访问作用域内部的局部变量，那么该变量：
 *      1.要么直接就用final修饰，是一个局部常量。
 *      2.要么就是一个事实上的常量，即只能赋值一次，相当于用final修饰它。
 *
 * 为什么这么设计呢?
 * 这是因为局部变量,和对象的生命周期存在冲突
 * 方法调用结束,局部变量销毁
 * 但对象可能还仍然存在,这时对象如果还要访问局部变量,去哪里访问呢?
 * 为了解决这个问题,JVM在创建:
 *      访问了作用域内部局部变量的局部内部类对象时
 *      会将该访问的局部变量,作为对象的成员变量
 *      这样以后,每次对象访问局部变量,实际上访问的是自己的成员变量
 *      这样就解决了生命周期的冲突
 *
 * 但是解决生命周期冲突问题的方案,又引入了新的问题:
 *      从代码上看,局部内部类访问的是局部变量
 *      但是从内存上看,从实际上看,局部内部类访问的是自身成员变量
 *      这样就出现新的冲突了:
 *      如果在修改了该局部变量的取值,
 *          从代码上来说,修饰的是局部变量
 *          但实际应该修改成员变量
 *      也就是说,如果允许修改它的取值
 *      那就需要JVM再次同步成员变量的取值修改
 *
 * 不管如何,Java没有采取同步的设计,而是直接禁止修改,避免同步问题
 *
 * 在Java8之前版本的JDK中，如果不给能在局部内部类内部，访问的局部变量直接加上final修饰，会编译报错。
 * 但是在Java8之后该final修饰符被隐藏在了底层，程序员可以不用给该局部变量显式加final。这也是一种语法糖。
 *
 *
 * @since 15:07
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        EnclosedClazz ec = new EnclosedClazz();
        IA ia = ec.test();
        ia.method();
    }
}

class EnclosedClazz {
    public IA test() {
        int a = 10;
        class Inner implements IA {
            @Override
            public void method() {
                System.out.println(a);
                // System.out.println(a++);
            }
        }
        return new Inner();
    }
}

interface IA {
    void method();
}